using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing.Design;
using System.Collections;

using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Drawing;
using Camalon.Drawing;
using System.Drawing.Drawing2D;

namespace Camalon.Drawing.Design
{

	
	/// <summary>
	/// Summary description for ShapeProviderDesigner.
	/// </summary>
	public class ShapeProviderDesigner:System.Windows.Forms.Design.ControlDesigner
	{


		public override ICollection AssociatedComponents
		{
			get
			{
				Shape shape = this.ShapeProvider.Shape;
				ArrayList list = new ArrayList();
			
				if( _dragging) return list;//If we return the shape while dragging, then control does not drag!!!!!

				if( shape != null) list.Add(shape);
				return list;
			}
		}


		#region My Members
		private ShapeAdornment _adornment;
		#endregion My Members
		
		#region Constructor/Disposal

		public ShapeProviderDesigner()
		{
			//
			// TODO: Add constructor logic here
			//
		}


		protected override void Dispose(bool disposing)
		{

			if( disposing)
			{
				try
				{

					if( _mcsHelper != null) 
					{
						lock( _mcsHelper )
						{
							RemoveCommandHandlers();
							_mcsHelper.Restore();
						}
					}

					if( this.ShapeProvider != null)
					{
						if( this.ShapeProvider.Shape != null)
							this.ShapeProvider.Shape.PathBoundsChanged-=new ValueChangeEventHandler(ShapePathBoundsChanged);
						this.ShapeProvider.Paint-=new PaintEventHandler(Control_Paint);

					}


					if( _selectionService != null) 
					{
						_selectionService.SelectionChanged-=new EventHandler(SelectionService_SelectionChanged);
						_selectionService = null;
					}


					if( _changeService != null) 
					{
						_changeService.ComponentRemoving-=new ComponentEventHandler(ChangeService_ComponentRemoving);
						_changeService = null;
					}

					if( _designerHost != null)
					{
						_designerHost.LoadComplete-=new EventHandler(DesignerHost_LoadComplete);
						_designerHost = null;

					}
				


				}
				catch( Exception ex)
				{
					FileWatcher.WriteLine( ex.StackTrace);
				}

			}


			base.Dispose (disposing);

		}

		#endregion Constructor/Disposal

		#region Initialization

		static MenuCommandsHelper _mcsHelper;

		public override void Initialize(IComponent component)
		{
			try
			{

				base.Initialize (component);
				
				//Add paint event and invalidate
				if( this.ShapeProvider != null) 
					this.ShapeProvider.Paint+=new PaintEventHandler(this.Control_Paint);

				//Add selection and change events at the and..
				this.SelectionService.SelectionChanged+=new EventHandler(SelectionService_SelectionChanged);
				this.ChangeService.ComponentRemoving+=new ComponentEventHandler(ChangeService_ComponentRemoving);
				
				if( this.DesignerHost.Loading )
					this.DesignerHost.LoadComplete+=new EventHandler(DesignerHost_LoadComplete);//call this first

				//The contained shapes also might use those commnds and delete them when selected
				//Also see the SelectionChanged Event Handler Method....!
				if( _mcsHelper == null  )
					_mcsHelper = new MenuCommandsHelper( this.MenuCommandService, GetUsedCommandIDs());

				AddCommandHandlers();


			}
			catch( Exception ex)
			{
				FileWatcher.WriteLine( ex.StackTrace);
			}
		}


		#endregion Initialization

		#region Services

		private IComponentChangeService _changeService;
		protected IComponentChangeService ChangeService
		{
			get
			{ 
				try
				{
					if( _changeService == null) _changeService = GetService(typeof(IComponentChangeService)) as IComponentChangeService;
				}
				catch( Exception ex)
				{
					FileWatcher.WriteLine( ex.StackTrace);
				}

				
				return _changeService;
			}
		}


		private ISelectionService _selectionService;
		protected ISelectionService SelectionService
		{
			get
			{ 
				try
				{
					if( _selectionService == null) _selectionService = GetService(typeof(ISelectionService)) as ISelectionService;
				}
				catch( Exception ex)
				{
					FileWatcher.WriteLine( ex.StackTrace);
				}

				return _selectionService;
			}
		}

		private IDesignerHost _designerHost ;
		protected IDesignerHost DesignerHost
		{
			get
			{
				try
				{
					if( _designerHost == null) _designerHost = (IDesignerHost)GetService(typeof(IDesignerHost));
				}
				catch( Exception ex)
				{
					FileWatcher.WriteLine( ex.StackTrace);
				}

				
				return _designerHost;
			}
		}

		private IMenuCommandService _menuCommandService;

		protected IMenuCommandService MenuCommandService
		{
			get
			{
				try
				{
					if( _menuCommandService == null) _menuCommandService = GetService(typeof(IMenuCommandService)) as IMenuCommandService;
				}
				catch( Exception ex)
				{
					FileWatcher.WriteLine( ex.StackTrace);
				}

				return _menuCommandService;
			}

		}

		#endregion Services

		#region Misc Properties

		protected IShapeProvider ShapeProvider
		{
			get
			{
				try
				{
					return this.Control as IShapeProvider;// ShapeControl;
				}
				catch( Exception ex)
				{
					FileWatcher.WriteLine( ex.StackTrace);
					return null;
				}

			}

		}

		#endregion Misc Properties
		
		#region Adornment

		private ShapeAdornment Adornment 
		{
			get	{	return _adornment;	}
		}

		private void RefreshAdornment()
		{
			try
			{
				//Gets the adornment object for the shape from its designer. 

				if( this.DesignerHost == null || this.Shape== null) return;

				if( _adornment != null && _adornment.Shape == this.Shape) return;

				this.Shape.PathBoundsChanged-=new ValueChangeEventHandler(ShapePathBoundsChanged);
				
				IDesigner designer = this.DesignerHost.GetDesigner( this.Shape );

				if( designer == null){ _adornment = null; return; }


				ISupportAdornment ad =   designer as ISupportAdornment;
				_adornment = ad == null ? null: ad.Adornment;

				this.Shape.PathBoundsChanged+=new ValueChangeEventHandler(ShapePathBoundsChanged);

			
			}
			catch( Exception ex)
			{
				FileWatcher.WriteLine( ex.StackTrace);
			}
			
		}
		#endregion Adornment

		#region Design Time Properties



		[Category( "Shape")] 
		[Browsable( true )]
		[DefaultValue( null)]
		public Shape Shape
		{
			get
			{
				try
				{
					if( this.ShapeProvider == null) return null;
				
					return this.ShapeProvider.Shape;
				}
				catch( Exception e)
				{
					FileWatcher.WriteLine( e.StackTrace);
					
				}
				return null;
			}
			set
			{
				try
				{

					//if( this.ShapeProvider == null) return;
					// When the designer loading and if the Shape has less protection ( modifier) tha ShapeControl then 
					// the designer sets the Shape property to null. To prevent this:
					// the designer sets all properties that references components with a higher protection from components with hiher
					//					if( this.ShapeProvider.Shape != null && value == null && this.DesignerHost != null && this.DesignerHost.Loading ) return;
					//----------------------------------------------------------------------------------------------------------------
					if( value == this.ShapeProvider.Shape) return;
			
					this.ShapeProvider.Shape = value;

//					if( value == null) FileWatcher.WriteLine(TypeDescriptor.GetComponentName( this.ShapeProvider ) + "::Shape removed.");

					RefreshAdornment();
					
				}
				catch( Exception e)
				{
					FileWatcher.WriteLine( e.StackTrace);
				}
			}
		}



		Color	_gridColor				= Color.Silver;
		Pen		_linePenBase			= new Pen(Color.FromArgb(96,Color.Silver),1.0f);
		Pen		_linePenBold			= new Pen(Color.FromArgb(196,Color.Silver),1.0f);

		Size	_gridSize				= new Size(10,10);
		int		_gridPageSize			= 5;
		bool	_snapToGrid				= true;
		bool	_drawGrid				= true;


		[Category("Design")]
		[DefaultValue(typeof(Size),"10,10")]
		[DesignOnly( true )]
		public Size GridSize
		{
			get
			{	
				return _gridSize;
			}
			set
			{
				_gridSize = value;
				if( this.ShapeProvider != null) this.ShapeProvider.Invalidate();
			}
		}

		[Category("Design")]
		[DefaultValue(true)]
		[DesignOnly( true )]
		public bool DrawGrid
		{
			get
			{	
				return _drawGrid;
			}
			set
			{
				_drawGrid = value;
				if( this.ShapeProvider != null) this.ShapeProvider.Invalidate();
			}
		}

		[Category("Design")]
		[DefaultValue(5)]
		[DesignOnly( true )]
		public int GridPageSize
		{
			get { return _gridPageSize;}
			set
			{
				_gridPageSize = value;
				if( this.ShapeProvider != null) this.ShapeProvider.Invalidate();
			}
		}
		
		[Category("Design")]
		[DefaultValue(true)]
		[DesignOnly( true )]
		public bool SnapToGrid
		{
			get
			{	
				return _snapToGrid;
			}
			set
			{
				_snapToGrid = value;
				if( this.ShapeProvider != null) this.ShapeProvider.Invalidate();
			}
		}

		[Category("Design")]
		[DefaultValue(typeof(Color), "Silver")]
		[DesignOnly( true )]
		public Color GridColor
		{
			get
			{
				return _gridColor;
			}
			set
			{
				_gridColor = value;
				if( _linePenBase != null) { _linePenBase.Dispose(); _linePenBase = null;}
				if( _linePenBold != null) { _linePenBold.Dispose(); _linePenBold = null;}

				_linePenBase			= new Pen(Color.FromArgb(96,value),1.0f);
				_linePenBold			= new Pen(Color.FromArgb(196,value),1.0f);
				
				if( this.ShapeProvider != null) this.ShapeProvider.Invalidate();
			}

		}





		protected override void PreFilterProperties(IDictionary properties)
		{
			base.PreFilterProperties (properties);

			properties["GridColor"] = TypeDescriptor.CreateProperty(
				typeof(ShapeProviderDesigner), 
				"GridColor", 
				typeof(Color));


			properties["SnapToGrid"] = TypeDescriptor.CreateProperty(
				typeof(ShapeProviderDesigner), 
				"SnapToGrid", 
				typeof(bool));

			properties["GridPageSize"] = TypeDescriptor.CreateProperty(
				typeof(ShapeProviderDesigner), 
				"GridPageSize", 
				typeof(int));


			properties["DrawGrid"] = TypeDescriptor.CreateProperty(
				typeof(ShapeProviderDesigner), 
				"DrawGrid", 
				typeof(bool));

			properties["GridSize"] = TypeDescriptor.CreateProperty(
				typeof(ShapeProviderDesigner), 
				"GridSize", 
				typeof(Size));

			properties["Shape"] = TypeDescriptor.CreateProperty(
				typeof(ShapeProviderDesigner), 
				"Shape", 
				typeof(Shape));

		}


		#endregion Design Time Properties

		#region Event Handlers
		RectangleF _oldInvalidatingBounds = RectangleF.Empty;
		private void ShapePathBoundsChanged(object sender, ValueChangeEventArgs e)
		{
			try
			{
				
				//FileWatcher.WriteLine("Shape Path bounds changed");
				if( this.ShapeProvider != null) this.ShapeProvider.Invalidate( );

			}
			catch( Exception ex)
			{
				FileWatcher.WriteLine( ex.StackTrace);

			}
		}
		#endregion Event Handlers

		#region Context Menu

		private bool ShowShapeContextMenu( int x, int y)
		{
			try
			{
				if( this.Shape == null) return false;
				if( this.ShapeProvider.Clip || this.ShapeProvider.ScalingResize ) return false;

				//Show the context menu of the shape when the shape clicked

				Point point = new Point( x,y);
				Point clientPoint =this.ShapeProvider.PointToClient( point);

			
				if	(this.Adornment != null && 
					(this.Adornment.HitTest( clientPoint, false ) != CursorStatus.None  || this.Adornment.PointsEditingMode ))
				{
					this.Adornment.LastHitTest = clientPoint;

					this.SelectionService.SetSelectedComponents( new IComponent[]{ this.Shape}, SelectionTypes.Replace);
					IMenuCommandService mcs = this.Shape.Site.GetService( typeof( IMenuCommandService)) as IMenuCommandService;
					
					if( mcs != null) 
					{
						mcs.ShowContextMenu( MenuCommands.TraySelectionMenu, x, y);
						return true;
					}
				}

			}
			catch( Exception ex)
			{
				FileWatcher.WriteLine( ex.StackTrace);

			}

			return false;
		}
		

		protected override void OnContextMenu(int x, int y)
		{
			//We show the context menu of Shape if controls shape is clicked
			if( this.ShowShapeContextMenu( x, y)) return;

			base.OnContextMenu (x, y);
		}

		#endregion Context Menu

		#region Service Event Handlers
		private void DesignerHost_LoadComplete(object sender, EventArgs e)
		{

		}



		private void ChangeService_ComponentRemoving(object sender, ComponentEventArgs e)
		{
			try
			{
//				if(this.DesignerHost == null ||  this.DesignerHost.Loading) return;
				// If the associated Shape is removed set the shape value to null
				if(e.Component == this.Shape)
				{
//					FileWatcher.WriteLine(TypeDescriptor.GetComponentName( this.ShapeProvider ) + "::Shape removed 2.");
					PropertyDescriptor	propShape = TypeDescriptor.GetProperties(this.ShapeProvider)["Shape"];
					if( propShape != null) propShape.SetValue( this.ShapeProvider, null);

				}

				

				if( _mcsHelper != null )// Mixed menu helper
						lock( _mcsHelper )
							if(!( this.SelectionService.PrimarySelection is Shape) ) _mcsHelper.Restore();

			}
			catch( Exception ex)
			{
				FileWatcher.WriteLine( ex.StackTrace);

			}

		}

		private bool IsPrimarySelection
		{
			get
			{
				if( this.SelectionService == null) return false;
				if( this.Shape == null) return false;
				return this.SelectionService.PrimarySelection == this.Shape;
			}
		}


		private void SelectionService_SelectionChanged(object sender, EventArgs e)
		{
			try
			{

				if(this.DesignerHost == null ||  this.DesignerHost.Loading) return;//CAUTION..DO NOT DELETE...

				if( _mcsHelper != null )// Mixed menu helper
				{ 
					lock( _mcsHelper )
					{
						if( this.IsPrimarySelection ) _mcsHelper.Add();
						else if(!( this.SelectionService.PrimarySelection is Shape) ) _mcsHelper.Restore();
					}
				}



			
				//While dragging shape, either ESC-Key pressed or mouse button released (up) outside of the control, then ...
				//Cancel dragging (Do not call OnMouseDragEnd directly here!!!!)
				if( _dragDropData != null && !this.IsPrimarySelection ) EndDragging(true );
				else if( this.ShapeProvider != null)
				{
					if( this.Adornment == null) RefreshAdornment();
					this.ShapeProvider.Invalidate();
				}

					
			}
			catch( Exception ex)
			{
				FileWatcher.WriteLine( ex.StackTrace);

			}
		}


		#endregion Service Event Handlers

		#region Cursor
		protected override void OnSetCursor()
		{
			//We set cursor using adornment if cursor is over the shape..
			if( this.DesignerHost == null ||  
				this.DesignerHost.Loading ||
				this.Shape == null || 
				this.Adornment == null || 
				this.ShapeProvider.Clip || 
				this.ShapeProvider.ScalingResize) { base.OnSetCursor(); return;}

		
			try
			{
				if( _dragDropData != null)
				{
					Cursor.Current = ShapeAdornment.GetCursor( _dragDropData.CursorStatus );
					return;
				}

				Point point = Form.MousePosition;
				Point clientPoint =this.ShapeProvider.PointToClient( point);

				if( this.Adornment != null && this.Adornment.PointsEditingMode)
				{	//Check whether adornment is in points editing mode
					CursorStatus cs = this.Adornment.HitTest( clientPoint, false );

					if( cs != CursorStatus.None ) Cursor.Current = ShapeAdornment.GetCursor( cs );
					else Cursor.Current = ShapeAdornment.GetCursor( CursorStatus.MouseOver );

					return;
				}
				else if( this.IsPrimarySelection )
				{
					CursorStatus cs = this.Adornment.HitTest( clientPoint, false );
					if( cs != CursorStatus.None ) 
					{
						Cursor.Current = ShapeAdornment.GetCursor( cs ); 
						return;
					}
				}
				else if( this.Shape.HitTest( clientPoint)  )
				{
					Cursor.Current = ShapeAdornment.GetCursor( CursorStatus.MouseOver );
					return ;
				}
			}
			catch( Exception e)
			{
				FileWatcher.WriteLine("GetHitTest::" + e.Message + "\n" + e.StackTrace);
			}

			//If not over the shape the use base cursor
			base.OnSetCursor();
	

			
		}

		#endregion Cursor

		#region MOUSE DRAG & DROP DATA

		private DragDropData	_dragDropData		;


		#endregion MOUSE DRAG & DROP DATA

		#region Mouse Drag & Drop

		protected internal Point SnapGridPoint( Point clientPoint )
		{
			return this.SnapGridPoint( clientPoint, false );
		}

		protected internal Point SnapGridPoint( Point clientPoint, bool forceSnap )
		{
			if( _snapToGrid || forceSnap )
			{
				//My version
				clientPoint.X = _gridSize.Width * (clientPoint.X / _gridSize.Width);
				clientPoint.Y = _gridSize.Height * (clientPoint.Y / _gridSize.Height);
			}

			return clientPoint;
		}


		#region Mouse Move Methods

		private void OnMoveShape(Point offset)
		{

			try
			{
				if( this.Shape == null) return;

				Shape shape = this.Shape;
				ShapeAdornment a = this.Adornment;

				Rectangle oldRect = a.InvalidatingBounds;
				

				//Invert if shape ScalingResized.
				offset = Point.Round( shape.ScalingResizeTransformPoint( offset, true ) );//new

				Point position = shape.Position;
				Point oldPosition = position;
				position.Offset( offset.X, offset.Y );

				if( shape.Position != position ) shape.Position = position;
			}
			catch( Exception e)
			{
				FileWatcher.WriteLine( e.StackTrace);

			}


		}

		private void OnResizeShape( Point offset )
		{
			if( this.Shape == null) return;

			Shape shape = this.Shape;
			ShapeAdornment a = this.Adornment;

			Point ptCurrent		= _dragDropData.CurrentMousePosition;

			CursorStatus cursorStatus = _dragDropData.CursorStatus;
			
			int rem = int.MaxValue; 
			Math.DivRem( shape.Rotation, 360, out rem ); 
			if( rem != 0 )
			{
				Matrix m = new Matrix();
				PointF anchor = shape.GetRotatingPoint();
				m.RotateAt(-shape.Rotation, anchor, MatrixOrder.Append);

				Point[] offsetVector = new Point[]{ offset};
				m.TransformVectors( offsetVector );
				offset = offsetVector[0];

				Point[] transCurrent = new Point[]{ ptCurrent};
				m.TransformPoints( transCurrent );
				ptCurrent = transCurrent[0];
			}
			



			Size minSize = shape.MinSize;

			RectangleF shapeBounds = shape.Bounds;
			if( cursorStatus == CursorStatus.Right || 
				cursorStatus == CursorStatus.BottomRight ||
				cursorStatus == CursorStatus.TopRight)
				if( offset.X != 0 )
					if( shape.Bounds.Width > shape.MinSize.Width ||  ptCurrent.X > shape.Bounds.Right)
					{
						SizeF size	= shapeBounds.Size ;
						size.Width += offset.X;
						size.Width = size.Width < minSize.Width ? minSize.Width : size.Width;

						shapeBounds.Size = size;
					}



			if( cursorStatus == CursorStatus.Bottom|| 
				cursorStatus == CursorStatus.BottomRight ||
				cursorStatus == CursorStatus.BottomLeft)//Location fixed:OK
				if( offset.Y != 0 )
					if( shape.Size.Height > shape.MinSize.Height ||  ptCurrent.Y >= shape.Bounds.Bottom)
					{
						SizeF size	= shapeBounds.Size;
						size.Height += offset.Y;
						size.Height = size.Height < minSize.Height ? minSize.Height : size.Height;
					
						shapeBounds.Size = size;

					}

			if( cursorStatus == CursorStatus.Top|| 
				cursorStatus == CursorStatus.TopLeft ||
				cursorStatus == CursorStatus.TopRight) // Bottom fixes
				if( offset.Y != 0 )
					if( shape.Size.Height > shape.MinSize.Height ||  ptCurrent.Y <= shape.Bounds.Top)
					{
						RectangleF currentBounds = shapeBounds;
						SizeF size	= shapeBounds.Size ;
						size.Height -= offset.Y;
						size.Height = size.Height < minSize.Height ? minSize.Height : size.Height;
					
						shapeBounds.Size = size;

						PointF position = shapeBounds.Location;
						position.Y += offset.Y;

						if( position.Y + size.Height > currentBounds.Bottom )
							position.Y = currentBounds.Bottom - minSize.Height;

						shapeBounds.Location = position;

					}

			if( cursorStatus == CursorStatus.Left|| 
				cursorStatus == CursorStatus.TopLeft ||
				cursorStatus == CursorStatus.BottomLeft)//Right fixed
				if( offset.X != 0 )
					if( shape.Size.Width > shape.MinSize.Width ||  ptCurrent.X <= shape.Position.X )
					{
						SizeF size	= shapeBounds.Size;
						size.Width -= offset.X;
						size.Width = size.Width < minSize.Width ? minSize.Width : size.Width;

						shapeBounds.Size = size;

						PointF position = shapeBounds.Location;// shape.Position;
						position.X += offset.X;

						shapeBounds.Location = position;

					}

			
			if( shape.Bounds != shapeBounds) shape.Bounds = shapeBounds;	
		}
		

		private void OnRotateShape( )
		{
			if( this.Shape == null) return;

			Shape shape = this.Shape;

			Point ptCurrent				= _dragDropData.CurrentMousePosition;
			Point anchorPoint			= Point.Round(_dragDropData.RotationAnchor);

			int beginRotate				= shape.Rotation;
			int endRotate				= shape.GetRotatingAngle( ptCurrent );
			int delta					= endRotate - beginRotate;

			ShapeAdornment a	= this.Adornment;
			shape.Rotation += delta;
			a.BeginRotation( ptCurrent );


		}

		private void OnScaleShape( Point offset )
		{
			if( this.Shape == null) return;

			Shape shape					= this.Shape;
			RectangleF pb				= shape.GetPathBounds();		
			CursorStatus cursorStatus	= _dragDropData.CursorStatus;

			if( shape.Scale.AppendRotate == false)
			{
				int rem = int.MaxValue; 
				Math.DivRem( shape.Rotation, 360, out rem ); 
				if( rem != 0 )
				{
					Matrix m = new Matrix();
					PointF anchor = shape.GetRotatingPoint();
					m.RotateAt(-shape.Rotation, anchor, MatrixOrder.Append);

					Point[] offsetVector = new Point[]{ offset};
					m.TransformVectors( offsetVector );
					offset = offsetVector[0];
				}
			}


			switch( cursorStatus )
			{
				case CursorStatus.ScaleLeft:
					offset.X	= -offset.X; 
					offset.Y	= 0;
					break;
				case CursorStatus.ScaleRight:
					offset.Y	= 0;
					break;
				case CursorStatus.ScaleTop:
					offset.Y	= -offset.Y;
					offset.X	= 0; 
					break;
				case CursorStatus.ScaleBottom:
					offset.X	= 0;
					break;
				default:return;
			}
			
				
			shape.AddScale( offset.X, offset.Y );
			


		}


		private void OnShearShape( Point offset )
		{
			if( this.Shape == null) return;

			Rectangle oldRect	= Rectangle.Empty;
			Rectangle newRect	= Rectangle.Empty;

			Shape primaryShape	=  this.Shape;//_dragDropData.PrimaryAttributes.Shape;
			Point ptCurrent		= _dragDropData.CurrentMousePosition;
			bool shearX			= _dragDropData.CursorStatus == CursorStatus.ShearX;

			//Calculate shear
			//-------------------------------------------------------------------------------------------
			RectangleF pathBounds	 = primaryShape.GetBasePathBounds();
			Shear shear = primaryShape.Shear;

			if( shear.AppendRotate )
			{
				Matrix m = new Matrix();
				m.RotateAt(primaryShape.Rotation, primaryShape.GetRotatingPoint(), MatrixOrder.Append);
				using(GraphicsPath path = primaryShape.CloneBasePath())
				{
					path.Transform( m );
					pathBounds = path.GetBounds();
				}
			}
			else if( primaryShape.Rotation != 0 )
			{
				Matrix m = new Matrix();
				PointF anchor = primaryShape.GetRotatingPoint();
				m.RotateAt(-primaryShape.Rotation, anchor, MatrixOrder.Append);

				Point[] transCurrent = new Point[]{ ptCurrent };
				m.TransformPoints( transCurrent );
				ptCurrent = transCurrent[0];
			
			}
			
			PointF center = RectangleUtil.CenterPoint( pathBounds );
			// y = ( n * x ) + b,  
			// x = ( y - b ) / n, 
			// n = ( y1 - y2 ) / ( x1 - x2 ) 
			// b = y2 - ( n * x2 ) = y1 - ( n * x1 )
			
			float n = (center.Y - ptCurrent.Y)/( center.X - ptCurrent.X  );
			float b = ( ptCurrent.Y - ( n * ptCurrent.X));

			PointF ptis = PointF.Empty;
			Shear newShear = shear;


			if( shearX )
			{
				try
				{
					ptis.Y		= pathBounds.Bottom; 
					ptis.X		= ( ptis.Y - b )/n;
					newShear.X	= Convert.ToInt32( System.Math.Round(ptis.X - center.X ));
				}
				catch//(OverflowException ex)
				{
					//TODO : Handle OverflowException
					newShear.X  = 0;
				}
			}
			else
			{
				try
				{
					ptis.X		= pathBounds.Left;
					ptis.Y		= (n*ptis.X) + b;
					newShear.Y	= Convert.ToInt32( System.Math.Round(center.Y - ptis.Y));
				}
				catch//(OverflowException ex)
				{
					//TODO : Handle OverflowException
					newShear.Y =0;
				}
			}

			//FileWatcher.WriteLine( "SchnittPunkt: " + ptis.ToString());
			//-------------------------------------------------------------------------------------------

			Shear shearOffset = new Shear( newShear.X - shear.X ,newShear.Y - shear.Y ); //new

			if( shearOffset.X != 0 || shearOffset.Y != 0)//new
				//				foreach( object shapeObject in selectedComponents ) 
				//					if( shapeObject is Shape )
			{
				Shape shape = this.Shape;//(Shape)shapeObject;

				ShapeAdornment a	= this.Adornment;
				oldRect = Rectangle.Union( oldRect, a.InvalidatingBounds );


				//if( shape == primaryShape)
				a.BeginShearing( _dragDropData.CurrentMousePosition, shearX );

				Shear oldShear = shape.Shear;//new
				oldShear.X	+=  shearOffset.X;
				oldShear.Y	+=  shearOffset.Y;
				shape.Shear = oldShear;// newShear; //new

				newRect = Rectangle.Union( newRect, a.InvalidatingBounds );
			
			}

			//			if( primaryShape == _rootDesigner.ShapeContainer)
			//				InvalidateShapes();
			//			else
			//			{
			//				Rectangle union = Rectangle.Union( oldRect, newRect);
			//				if( union != Rectangle.Empty ) InvalidateShapeBounds( union );
			//			}
		}

		private void OnWarpShape( Point offset )
		{
			if( this.Shape == null) return;


			Shape shape			= this.Shape;
			CursorStatus cursorStatus = _dragDropData.CursorStatus;
			
			int rem = int.MaxValue; 
			Math.DivRem( shape.Rotation, 360, out rem ); 
			if( rem != 0 )
			{
				Matrix m = new Matrix();
				PointF anchor = shape.GetRotatingPoint();
				m.RotateAt(-shape.Rotation, anchor, MatrixOrder.Append);

				Point[] offsetVector = new Point[]{ offset};
				m.TransformVectors( offsetVector );
				offset = offsetVector[0];
			}


			Point topLeft		= shape.Warp.TopLeft;
			Point topRight		= shape.Warp.TopRight;
			Point bottomLeft	= shape.Warp.BottomLeft;
			Point bottomRight	= shape.Warp.BottomRight;


			if( cursorStatus == CursorStatus.WarpTopLeft)
			{
				topLeft.X += offset.X;
				topLeft.Y += offset.Y;
			}

			if( cursorStatus == CursorStatus.WarpTopRight)
			{
				topRight.X += offset.X;
				topRight.Y += offset.Y;
			}
			if( cursorStatus == CursorStatus.WarpBottomLeft)
			{
				bottomLeft.X += offset.X;
				bottomLeft.Y += offset.Y;
			}
			if( cursorStatus == CursorStatus.WarpBottomRight)
			{
				bottomRight.X += offset.X;
				bottomRight.Y += offset.Y;
			}

			//------------------------------------------
			if( cursorStatus == CursorStatus.WarpTop)
			{
				topLeft.Y += offset.Y;
				topLeft.X += offset.X;

				topRight.Y += offset.Y;
				topRight.X += offset.X;
			}
			if( cursorStatus == CursorStatus.WarpBottom)
			{
				bottomRight.Y += offset.Y;
				bottomRight.X += offset.X;

				bottomLeft.Y += offset.Y;
				bottomLeft.X += offset.X;
			}

			if( cursorStatus == CursorStatus.WarpRight)
			{
				topRight.X		+= offset.X;
				topRight.Y		+= offset.Y;

				bottomRight.X	+= offset.X;
				bottomRight.Y	+= offset.Y;
			}
			if( cursorStatus == CursorStatus.WarpLeft)
			{
				bottomLeft.X += offset.X;
				bottomLeft.Y += offset.Y;

				topLeft.X += offset.X;
				topLeft.Y += offset.Y;
			}

			shape.Warp = new Warp( topLeft, topRight,bottomLeft, bottomRight, shape.Warp.WarpMode);
				


		}

		private void OnEditControlPoints(Point offset)
		{
			if( this.Shape == null) return;
		

			Shape shape = this.Shape;
			ShapeAdornment a = this.Adornment;
			int editingIndices = a.EditingControlPointIndices;
			if( editingIndices == -1) return;

			Point ptCurrent		= _dragDropData.CurrentMousePosition;

			a.BeginEditControlPoint( ptCurrent );


			int rem = int.MaxValue; 
			Math.DivRem( shape.Rotation, 360, out rem ); 
			if( rem != 0 )
			{
				Matrix m = new Matrix();
				PointF anchor = shape.GetRotatingPoint();
				m.RotateAt(-shape.Rotation, anchor, MatrixOrder.Append);

				Point[] transCurrent = new Point[]{ ptCurrent};
				m.TransformPoints( transCurrent );
				ptCurrent = transCurrent[0];

			}
	

			PointF[] controlPoints = shape.ControlPoints;
			PointF ptEditing = controlPoints[ editingIndices];

			ptEditing = ptCurrent;
			controlPoints[ editingIndices] = ptEditing;
			shape.ControlPoints =  controlPoints;


		}

		private void OnEditPoints(Point offset)
		{
			if( this.Shape == null) return;
		

			VectorShape shape = this.Shape as VectorShape;
			if( shape == null) return;
			ShapeAdornment a = this.Adornment;
			int editingIndices = a.EditingPointIndices;
			if( editingIndices == -1) return;

			Point ptCurrent		= _dragDropData.CurrentMousePosition;

			a.BeginEditPoint( ptCurrent );

			int rem = int.MaxValue; 
			Math.DivRem( shape.Rotation, 360, out rem ); 
			if( rem != 0 )
			{
				Matrix m = new Matrix();
				PointF anchor = shape.GetRotatingPoint();
				m.RotateAt(-shape.Rotation, anchor, MatrixOrder.Append);

				Point[] transCurrent = new Point[]{ ptCurrent};
				m.TransformPoints( transCurrent );
				ptCurrent = transCurrent[0];

			}
	

			AnchorPoint[] controlPoints = shape.Points;
			AnchorPoint ptEditing = controlPoints[ editingIndices];
			ptEditing.Point = ptCurrent;
			controlPoints[editingIndices] = ptEditing;
			shape.Points =  controlPoints;

		}

		#endregion Mouse Move Methods


		#region Commit Drag Methods
		private void CommitScale()
		{
			if (_dragDropData == null) return;


			Scale startScale	= _dragDropData.PrimaryAttributes.Scale;
			Scale endScale		= this.Shape.Scale;

			if( !startScale.Equals( endScale ))
			{
				DesignerTransaction tx = this.DesignerHost.CreateTransaction("Shapes scaled");

				try
				{
					PropertyDescriptor	propScale	 = TypeDescriptor.GetProperties(typeof( Shape ))["Scale"];

					Scale newScale= endScale;;
					this.Shape.Scale = startScale;// Set Old scale;
					propScale.SetValue(this.Shape,newScale);//Set new scale

					tx.Commit();
				}
				catch
				{
					tx.Cancel();
					throw;
				}
			}

		}

		private void CommitWarp()
		{
			if (_dragDropData == null) return;


			Warp startWarp	= _dragDropData.PrimaryAttributes.Warp;
			Warp endWarp	= this.Shape.Warp;

			if( startWarp.Equals( endWarp )) return;

			DesignerTransaction tx = this.DesignerHost.CreateTransaction("Shapes warped");
			if( tx == null) return;

			try
			{
				PropertyDescriptor	propWarp	 = TypeDescriptor.GetProperties(typeof( Shape ))["Warp"];

				Warp newWarp= this.Shape.Warp;
				this.Shape.Warp = startWarp;// Set Old scale;
				propWarp.SetValue(this.Shape,newWarp);//Set new scale

				tx.Commit();
			}
			catch
			{
				tx.Cancel();
				throw;
			}

		}

		private void CommitRotate()
		{
			try
			{
				//FileWatcher.WriteLine("CommitRotate called");

				if (_dragDropData == null) return;

				PropertyDescriptor	propRotate		= TypeDescriptor.GetProperties(typeof( Shape ))["Rotation"];
				PropertyDescriptor	propPos			= TypeDescriptor.GetProperties(typeof( Shape ))["Position"];
					
				int startRotate		= _dragDropData.PrimaryAttributes.Rotation;
				int endRotate		= this.Shape.Rotation;


				if( startRotate != endRotate)
				{
					Shape shape = this.Shape;
					ShapeAttributes att = _dragDropData.PrimaryAttributes;


					//---------------------------------------------------------------------------------------
					shape.UnlockRotation();
					//--------------------------------------------------------------------------------------

					DesignerTransaction tx = this.DesignerHost.CreateTransaction("Rotation");

					try
					{
						//Commit Move
						//----------------------------------------------------------------
						Rectangle newBounds = Rectangle.Round( shape.Bounds );
						Rectangle oldBounds = Rectangle.Round( att.Bounds );
						if( oldBounds.Location != newBounds.Location ) 
						{
							shape.Bounds = oldBounds;
							propPos.SetValue(shape,newBounds.Location);
						}

						//Commit Rotate
						//----------------------------------------------------------------
						if( att.Rotation != shape.Rotation) 
						{
							int newRotation= shape.Rotation;
							shape.Rotation = att.Rotation;// Set Old rotation;
							propRotate.SetValue(shape,newRotation);
						}

						tx.Commit();
					}
					catch
					{
						tx.Cancel();
						throw;
					}
					
				}

				//End Rotations-----------------------------------
				ShapeAdornment a = this.Adornment;
				if( a != null ) a.EndRotation();

			}
			catch( Exception e )
			{
				FileWatcher.WriteLine("Commiting rotation failed:"+e.Message);
			}
		}

		private void CommitShear()
		{
			if (_dragDropData == null) return;


			Shear startShear	= _dragDropData.PrimaryAttributes.Shear;
			Shear endShear		= this.Shape.Shear;

			if( !startShear.Equals( endShear ))
			{
				DesignerTransaction tx = this.DesignerHost.CreateTransaction("Shapes sheared");
				try
				{
					PropertyDescriptor	propShear	 = TypeDescriptor.GetProperties(typeof( Shape ))["Shear"];
					ShapeAttributes att = _dragDropData.PrimaryAttributes;

					Shear newShear= this.Shape.Shear;
					this.Shape.Shear = att.Shear;// Set Old scale;
					propShear.SetValue(this.Shape,newShear);//Set new scale

					tx.Commit();
				}
				catch
				{
					tx.Cancel();
				}
			}

			ShapeAdornment a = this.Adornment;
			if( a != null ) a.EndShearing();


		}


		private void CommitResize()
		{
			DesignerTransaction tx = null;
			try
			{

				if (_dragDropData == null) return;

				ShapeAttributes att = _dragDropData.PrimaryAttributes;
				Shape shape = this.Shape;

				//Unlock rotating anchor
				if( _dragDropData.Effect == DragDropData.DragEffect.Resize	) this.Shape.UnlockRotation();

				Rectangle newBounds = Rectangle.Round( this.Shape.Bounds );
				Rectangle oldBounds = Rectangle.Round( att.Bounds );

				if( oldBounds == newBounds ) return;

				tx = this.DesignerHost.CreateTransaction("Shape moved");

				PropertyDescriptor	propPos	 = TypeDescriptor.GetProperties(typeof( Shape ))["Position"];
				PropertyDescriptor	propSize = TypeDescriptor.GetProperties(typeof( Shape ))["Size"];
				PropertyDescriptor	propAnchorPoints = TypeDescriptor.GetProperties(typeof( VectorShape ))["Points"];


				shape.Bounds = oldBounds;
				if( newBounds.Location != oldBounds.Location)
					propPos.SetValue(shape,newBounds.Location);
				if( newBounds.Size != oldBounds.Size)
					propSize.SetValue(shape,newBounds.Size);

				if( shape is VectorShape )
				{
					VectorShape vs = (VectorShape)shape;
					AnchorPoint[] newAnchorPoints = vs.Points;
					vs.Points = att.Points;
					propAnchorPoints.SetValue( vs,newAnchorPoints );
				}

				tx.Commit();

			}
			catch
			{
				if( tx != null) tx.Cancel();
				throw;
			}
			
			
		}



		private void CommitEditControlPoints()
		{
			if (_dragDropData == null) return;

			Shape shape = this.Shape;
			ShapeAdornment a = this.Adornment;
			int editingIndices = a.EditingControlPointIndices;

			if( editingIndices == -1) return;

			PointF[] newCtrlPoints = shape.ControlPoints;
			PointF[] oldCtrlPoints = _dragDropData.PrimaryAttributes.ControlPoints;
			if( oldCtrlPoints[ editingIndices] != newCtrlPoints[ editingIndices]) 
			{
				PropertyDescriptor	propControlPoints		= TypeDescriptor.GetProperties(typeof( Shape ))["ControlPoints"];

				using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction("ControlPoints"))
				{
					shape.ControlPoints = oldCtrlPoints;
					propControlPoints.SetValue( shape, newCtrlPoints);
					
					IControlPointDesigner cpd = this.DesignerHost.GetDesigner( shape ) as IControlPointDesigner;
					if( cpd != null) cpd.EndEditControlPoints( );
					a.EndEditControlPoint();
					tx.Commit();
				}
			}


			shape.UnlockRotation();

			//a.EndEditControlPoint();MUst be set during the transaction...See above..!

		}

		private void CommitEditPoints()
		{
			if (_dragDropData == null) return;

			VectorShape shape = _dragDropData.PrimaryAttributes.Shape as VectorShape;

			if( shape == null) return;

			ShapeAdornment a = this.Adornment;
			int editingIndices = a.EditingPointIndices;

			if( editingIndices == -1) return;

			AnchorPoint[] newCtrlPoints = shape.Points;
			AnchorPoint[] oldCtrlPoints = _dragDropData.PrimaryAttributes.Points;
			if( oldCtrlPoints[ editingIndices] != newCtrlPoints[ editingIndices]) 
			{
				PropertyDescriptor	propPoints		= TypeDescriptor.GetProperties(typeof( VectorShape ))["Points"];

				using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction("Points"))
				{
					shape.Points = oldCtrlPoints;
					propPoints.SetValue( shape, newCtrlPoints);
					tx.Commit();
				}
			}

			shape.UnlockRotation();
			a.EndEditPoint();
		}

		#endregion Commit Drag Methods


		bool _dragging = false;//Do not delete this ... See [AssociatedComponents] property
		protected override void OnMouseDragBegin(int x, int y)
		{
			
			try
			{
				_dragging = true;
				_dragDropData = null;

				if( this.Shape == null || this.Adornment == null || this.ShapeProvider.Clip || this.ShapeProvider.ScalingResize) { base.OnMouseDragBegin (x, y);return;}

				Point point = new Point(x,y);
				Point clientPoint =this.ShapeProvider.PointToClient( point);

				CursorStatus cursorStatus = this.Adornment.HitTest( clientPoint, false );

				if(this.Adornment.PointsEditingMode || cursorStatus!= CursorStatus.None) 
				{
					if( cursorStatus == CursorStatus.None)  
						cursorStatus = CursorStatus.MouseOver;//Points editing mode is set

					_dragDropData								= new DragDropData();
					_dragDropData.CursorStatus					= cursorStatus;
					_dragDropData.LastMouseDown					= SnapGridPoint( clientPoint ); 
					_dragDropData.CurrentMousePosition			= SnapGridPoint( clientPoint ); 
					_dragDropData.PrimaryAttributes				= new ShapeAttributes( this.Shape );



					//MOUSE OVER ---------------------------------------------------------------------
					if( cursorStatus == CursorStatus.MouseOver )
						_dragDropData.Effect				= DragDropData.DragEffect.Move;
						//ROTATE -------------------------------------------------------------------------
					else if( cursorStatus == CursorStatus.Rotation )
						_dragDropData.Effect				= DragDropData.DragEffect.Rotation;
						//SCALE --------------------------------------------------------------------------
					else if( cursorStatus == CursorStatus.ScaleLeft )
						_dragDropData.Effect				= DragDropData.DragEffect.ScaleLeft;
					else if( cursorStatus == CursorStatus.ScaleTop)
						_dragDropData.Effect				= DragDropData.DragEffect.ScaleTop;
					else if( cursorStatus == CursorStatus.ScaleRight )
						_dragDropData.Effect				= DragDropData.DragEffect.ScaleRight;
					else if( cursorStatus == CursorStatus.ScaleBottom)
						_dragDropData.Effect				= DragDropData.DragEffect.ScaleBottom;
						//WARP ----------------------------------------------------------------------------
					else if( cursorStatus == CursorStatus.WarpBottomLeft)
						_dragDropData.Effect				= DragDropData.DragEffect.WarpBottomLeft;
					else if( cursorStatus == CursorStatus.WarpBottomRight)
						_dragDropData.Effect				= DragDropData.DragEffect.WarpBottomRight;
					else if( cursorStatus == CursorStatus.WarpTopLeft)
						_dragDropData.Effect				= DragDropData.DragEffect.WarpTopLeft;
					else if( cursorStatus == CursorStatus.WarpTopRight)
						_dragDropData.Effect				= DragDropData.DragEffect.WarpTopRight;
						//----------------------------------------------------------------------
					else if( cursorStatus == CursorStatus.WarpBottom)
						_dragDropData.Effect				= DragDropData.DragEffect.WarpBottom;
					else if( cursorStatus == CursorStatus.WarpRight)
						_dragDropData.Effect				= DragDropData.DragEffect.WarpRight;
					else if( cursorStatus == CursorStatus.WarpLeft)
						_dragDropData.Effect				= DragDropData.DragEffect.WarpLeft;
					else if( cursorStatus == CursorStatus.WarpTop)
						_dragDropData.Effect				= DragDropData.DragEffect.WarpTop;
						//SHEAR --------------------------------------------------------------------------
					else if( cursorStatus == CursorStatus.ShearX)
						_dragDropData.Effect				= DragDropData.DragEffect.ShearX;
					else if( cursorStatus == CursorStatus.ShearY)
						_dragDropData.Effect				= DragDropData.DragEffect.ShearY;
						//Edit control points --------------------------------------------------------------------------
					else if( cursorStatus == CursorStatus.EditControlPoints)
					{
						_dragDropData.Effect = DragDropData.DragEffect.EditControlPoints;

						IControlPointDesigner cpd = this.DesignerHost.GetDesigner( this.Shape ) as IControlPointDesigner;
						if( cpd != null) cpd.BeginEditControlPoints( );

					}
						//Edit free shape points --------------------------------------------------------------------------
					else if( cursorStatus == CursorStatus.EditPoints)
						_dragDropData.Effect = DragDropData.DragEffect.EditPoints;
						//RESIZE --------------------------------------------------------------------------
					else 
						_dragDropData.Effect				= DragDropData.DragEffect.Resize;


					//Lock rotation point if Resize or EditControlPoints or EditPoints
					bool lockRotationPoint = _dragDropData.Effect == DragDropData.DragEffect.Resize ||
						_dragDropData.Effect == DragDropData.DragEffect.EditControlPoints ||
						_dragDropData.Effect == DragDropData.DragEffect.EditPoints;

					if( lockRotationPoint )	this.Shape.LockRotation();

					//Read the rotating point if rotation
					if(_dragDropData.Effect == DragDropData.DragEffect.Rotation )	
						_dragDropData.RotationAnchor = this.Shape.GetRotatingPoint();
					//---------------------------------------------------------------------------------------



					//TODO:Test effect, Must be removed. Above code is to be used
					//_dragDropData.Effect	= DragDropData.DragEffect.Move;


				}



				

				this.Adornment.LastHitTest = clientPoint;



				//If shape not selected, then begin control dragging
				if( _dragDropData == null ) { base.OnMouseDragBegin (x, y); return;}
				else 
					this.SelectionService.SetSelectedComponents( new IComponent[]{ this.Shape}, SelectionTypes.Replace);

				//Invalidate Shape provider to actualize any adornment changes
				this.ShapeProvider.Invalidate( this.Adornment.InvalidatingBounds );

			}
			catch( Exception e)
			{
				FileWatcher.WriteLine("OnMouseDragBegin::" + e.Message + "\n" + e.StackTrace);
			}


		}


		protected override void OnMouseDragMove(int x, int y)
		{
			try
			{

				if( _dragDropData == null) {base.OnMouseDragMove (x, y);return;}

				Point offset = new Point( 0,0 );
				Point point = new Point( x, y );
				Point clientPoint = SnapGridPoint( this.ShapeProvider.PointToClient( point));
				offset.X = clientPoint.X - _dragDropData.CurrentMousePosition.X;
				offset.Y = clientPoint.Y - _dragDropData.CurrentMousePosition.Y;
				_dragDropData.CurrentMousePosition	= clientPoint;



				if( _dragDropData.Effect == DragDropData.DragEffect.Move )
					OnMoveShape( offset );
				else if( _dragDropData.Effect == DragDropData.DragEffect.Resize )
					OnResizeShape(offset);
				else if( _dragDropData.Effect == DragDropData.DragEffect.Rotation )
					OnRotateShape(  );
				else if( _dragDropData.Effect == DragDropData.DragEffect.ScaleLeft ||  
					_dragDropData.Effect == DragDropData.DragEffect.ScaleRight ||
					_dragDropData.Effect == DragDropData.DragEffect.ScaleTop || 
					_dragDropData.Effect == DragDropData.DragEffect.ScaleBottom )
					OnScaleShape( offset );
				else if( _dragDropData.Effect == DragDropData.DragEffect.ShearX || 
					_dragDropData.Effect == DragDropData.DragEffect.ShearY)
					OnShearShape( offset );
				else if
					( 	_dragDropData.Effect == DragDropData.DragEffect.WarpBottomLeft||  
					_dragDropData.Effect == DragDropData.DragEffect.WarpBottomRight ||
					_dragDropData.Effect == DragDropData.DragEffect.WarpTopLeft || 
					_dragDropData.Effect == DragDropData.DragEffect.WarpTopRight ||
					//-------------------------------------------------------------------
					_dragDropData.Effect == DragDropData.DragEffect.WarpLeft||  
					_dragDropData.Effect == DragDropData.DragEffect.WarpRight ||
					_dragDropData.Effect == DragDropData.DragEffect.WarpBottom || 
					_dragDropData.Effect == DragDropData.DragEffect.WarpTop )
					OnWarpShape( offset );
				else if( _dragDropData.Effect == DragDropData.DragEffect.EditControlPoints)
					OnEditControlPoints( offset);
				else if( _dragDropData.Effect == DragDropData.DragEffect.EditPoints)
					OnEditPoints( offset);

				base.OnMouseDragMove (x, y);

				//				if( this.ShapeProvider != null) this.ShapeProvider.Invalidate( this.Adornment.InvalidatingBounds);
			}
			catch( Exception e)
			{
				FileWatcher.WriteLine( e.StackTrace);

			}

		}


		protected override void OnMouseDragEnd(bool cancel)
		{	//Mouse up.. See also SelectionService_SelectionChanged(...) for cancel...

			try
			{
				_dragging = false;
				//If shape not selected, then end control dragging
				if( _dragDropData==null ) base.OnMouseDragEnd (cancel);
				else EndDragging( cancel );//othewise end the shape dragging

				_dragDropData = null;


			}
			catch( Exception e)
			{
				FileWatcher.WriteLine("OnMouseDragEnd::" + e.Message + "\n" + e.StackTrace);
			}


		}


	
		private void EndDragging( bool cancel )
		{
			try
			{
				//Commit or cancel drag operation..

				if( _dragDropData == null) return;

				if( cancel)
				{
					ShapeAttributes a	= _dragDropData.PrimaryAttributes;
					this.Shape.Bounds		= a.Bounds;
					this.Shape.Scale		= a.Scale;
					this.Shape.Rotation		= a.Rotation;
					this.Shape.Shear		= a.Shear;
					this.Shape.Warp			= a.Warp;

					if( this.Adornment != null && _dragDropData.CursorStatus == CursorStatus.Rotation )
					{
						this.Adornment.EndRotation();
						this.Adornment.EndShearing();
					}


				}
				else
				{
					if( _dragDropData.Effect == DragDropData.DragEffect.ScaleLeft || 
						_dragDropData.Effect == DragDropData.DragEffect.ScaleRight||
						_dragDropData.Effect == DragDropData.DragEffect.ScaleTop||
						_dragDropData.Effect == DragDropData.DragEffect.ScaleBottom)
					{	CommitScale();	return;	}

					if( _dragDropData.Effect == DragDropData.DragEffect.WarpBottomLeft || 
						_dragDropData.Effect == DragDropData.DragEffect.WarpBottomRight||
						_dragDropData.Effect == DragDropData.DragEffect.WarpTopLeft ||
						_dragDropData.Effect == DragDropData.DragEffect.WarpTopRight ||
						//--------------------------------------------------------
						_dragDropData.Effect == DragDropData.DragEffect.WarpLeft||  
						_dragDropData.Effect == DragDropData.DragEffect.WarpRight ||
						_dragDropData.Effect == DragDropData.DragEffect.WarpBottom || 
						_dragDropData.Effect == DragDropData.DragEffect.WarpTop	)
					{	CommitWarp();	return;	}

					if( _dragDropData.Effect == DragDropData.DragEffect.Rotation)
					{	CommitRotate();	return;	}

					if( _dragDropData.Effect == DragDropData.DragEffect.ShearX || 
						_dragDropData.Effect == DragDropData.DragEffect.ShearY )
					{	CommitShear();	return;	}

					if( _dragDropData.Effect == DragDropData.DragEffect.Move || _dragDropData.Effect == DragDropData.DragEffect.Resize)
					{	CommitResize();	return;	}

					if( _dragDropData.Effect == DragDropData.DragEffect.EditControlPoints)
					{	CommitEditControlPoints();	return;	}

					if( _dragDropData.Effect == DragDropData.DragEffect.EditPoints)
					{	CommitEditPoints();	return;	}



				}


				//Reset dragging.. Clean drag resources here...
				_dragDropData = null;
			}
			catch( Exception e)
			{
				FileWatcher.WriteLine( e.StackTrace);

			}

			


		}



		#endregion Mouse Drag & Drop

		#region Painting


		

		private void Control_Paint(object sender, PaintEventArgs e)
		{
			
			try
			{
				if( this.DesignerHost.Loading) return;
				//Paint shape adornments
				this.Paint( e.Graphics );
			}
			catch( Exception ex)
			{
				FileWatcher.WriteLine( ex.StackTrace);
			}	

		}

		protected void Paint(Graphics g)
		{

			IShapeProvider sp = this.ShapeProvider;
			Size  spSize	= sp.Size;
			Shape shape		= this.Shape;

			if( sp == null) return;

			GraphicsContainer gc = null;

			try
			{
				if( this.Shape != null) return;


				gc = g.BeginContainer();
				g.SmoothingMode = SmoothingMode.AntiAlias;
				//Paint dimmed background if no shape set.
				using(SolidBrush clipBrush = new SolidBrush( Color.FromArgb( 44, Color.RoyalBlue)))//44
					g.FillRectangle(clipBrush, new Rectangle(new Point(0,0), spSize) );
			}
			finally
			{
				if ( gc != null) g.EndContainer( gc);

				if( this.Adornment != null && this.IsPrimarySelection && !this.ShapeProvider.Clip )
				{
					if( this.ShapeProvider.ScalingResize)
					{
						if(  this.Shape.Scale.IsEmpty || 
							this.Shape.Shear.IsEmpty ||
							this.Shape.Warp.IsEmpty  ||
							this.Shape.Rotation == 0 )
							using(Pen		penDash = new Pen( Color.FromArgb(128,Color.Blue), 1.0f))
							{
								penDash.DashStyle = DashStyle.Dash;
								g.DrawPath( penDash, this.Shape.ClonePath() );
							}
					}


					//Draw Shape Adornment
					this.Adornment.DrawAdornments( g );
				}

				//Draw grid
				if( _drawGrid ) this.PaintGrid( g );



			}

		}



		protected void PaintGrid(Graphics g)
		{
			if( ! _drawGrid ) return;
			

			IShapeProvider sp = this.ShapeProvider;
			if( sp == null) return;
			Size  spSize	= sp.Size;



			GraphicsContainer container = g.BeginContainer();


			try
			{

				g.CompositingQuality = CompositingQuality.HighSpeed;
				g.PixelOffsetMode= PixelOffsetMode.HighSpeed;


				int gridWidth	= _gridSize.Width;
				int gridHeight  = _gridSize.Height;

	
				Size scrollSize = spSize;

			
				int hLines = scrollSize.Height  / gridHeight;
				int vLines = scrollSize.Width   / gridWidth;

				for( int i=1; i <= hLines; i++ )
				{	
					Pen pen = (i % _gridPageSize) == 0 ? _linePenBold:_linePenBase;
					g.DrawLine(pen, 0, i*gridHeight, scrollSize.Width , i*gridHeight);
				}

				for( int i=1; i <= vLines; i++ )
				{	
					Pen pen = (i % _gridPageSize) == 0 ? _linePenBold:_linePenBase;
					g.DrawLine(pen, i*gridWidth, 0, i*gridWidth, scrollSize.Height );
				}

			}
			catch( Exception e)
			{
				FileWatcher.WriteLine("RulingPanel::PaintGrid failed"+e.Message);
			}
			finally
			{
				g.EndContainer( container);
			}

		}


		#endregion

		#region Designer Verbs
		
		DesignerVerb _verbSnapToGrid = null;
		DesignerVerb _verbShowGrid = null;


		DesignerVerbCollection _verbs = null;
		public override DesignerVerbCollection Verbs
		{
			get
			{
				try
				{
					if( _verbs == null)
					{
						_verbs = new DesignerVerbCollection();

						_verbShowGrid =    new DesignerVerb("Show Grid", new EventHandler(OnShowGrid));
						_verbShowGrid.Checked = this.DrawGrid;

						_verbSnapToGrid =    new DesignerVerb("Snap to Grid", new EventHandler(OnSnapToGrid));
						_verbSnapToGrid.Checked = this.SnapToGrid;

					
						_verbs.Add( _verbShowGrid );
						_verbs.Add( _verbSnapToGrid);

					}

					return _verbs;
				}
				catch( Exception exc)
				{
					FileWatcher.WriteLine("ProviderDesigner::DesignerVerbCollection:"+ exc.StackTrace);
					FileWatcher.WriteLine("ProviderDesigner::DesignerVerbCollection:"+ exc.Message);
					throw exc;
				}
			}
		}




		private void OnShowGrid(object sender, EventArgs e)
		{
			try
			{
				using (DesignerTransaction tx = this.DesignerHost.CreateTransaction("DrawGrid"))
				{
					_verbShowGrid.Checked = !this.DrawGrid;
					PropertyDescriptor prop = TypeDescriptor.GetProperties(this.Component)["DrawGrid"];
					prop.SetValue( this.Component,_verbShowGrid.Checked );
					tx.Commit();
				}
			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("ShapeContainer::OnShowGrid:"+ exc.StackTrace);
				FileWatcher.WriteLine("ShapeContainer::OnShowGrid:"+ exc.Message);
				throw exc;
			}

		}
		private void OnSnapToGrid(object sender, EventArgs e)
		{
			try
			{
				using (DesignerTransaction tx = this.DesignerHost.CreateTransaction("SnapToGrid"))
				{
					_verbSnapToGrid.Checked = !this.SnapToGrid;
					PropertyDescriptor prop = TypeDescriptor.GetProperties(this.Component)["SnapToGrid"];
					prop.SetValue( this.Component,_verbSnapToGrid.Checked );
					tx.Commit();
				}
			}
			catch( Exception exc)
			{
				FileWatcher.WriteLine("ShapeContainer::OnSnapToGrid:"+ exc.StackTrace);
				FileWatcher.WriteLine("ShapeContainer::OnSnapToGrid:"+ exc.Message);
				throw exc;
			}


		}


		#endregion Designer Verbs

		#region MenuCommands and Event Handlers

		internal static CommandID[] GetUsedCommandIDs()
		{
			return new CommandID[]
				{
					MenuCommands.KeyMoveLeft,
					MenuCommands.KeyMoveRight,
					MenuCommands.KeyMoveDown,
					MenuCommands.KeyMoveUp,

					MenuCommands.KeyNudgeDown,
					MenuCommands.KeyNudgeLeft,
					MenuCommands.KeyNudgeRight,
					MenuCommands.KeyNudgeUp,

					MenuCommands.KeyNudgeHeightDecrease	,
					MenuCommands.KeyNudgeHeightIncrease	,
					MenuCommands.KeyNudgeWidthDecrease	,
					MenuCommands.KeyNudgeWidthIncrease	,

					MenuCommands.KeySizeWidthDecrease	,
					MenuCommands.KeySizeWidthIncrease	,
					MenuCommands.KeySizeHeightIncrease	,
					MenuCommands.KeySizeHeightDecrease	,
				
					
					//To be implemented
					//------------------------------------------------------------
					MenuCommands.AlignLeft,
					MenuCommands.AlignBottom,
					MenuCommands.AlignRight,
					MenuCommands.AlignToGrid,
					MenuCommands.AlignTop,
					MenuCommands.AlignVerticalCenters,
					MenuCommands.AlignHorizontalCenters,
					
					MenuCommands.CenterHorizontally,
					MenuCommands.CenterVertically,
					
					MenuCommands.HorizSpaceDecrease,
					MenuCommands.HorizSpaceIncrease,
					MenuCommands.HorizSpaceMakeEqual,
					MenuCommands.HorizSpaceConcatenate,

					MenuCommands.SizeToControlHeight,
					MenuCommands.SizeToControl,
					MenuCommands.SizeToControlWidth,
					MenuCommands.SizeToGrid,

					MenuCommands.VertSpaceDecrease,
					MenuCommands.VertSpaceIncrease,
					MenuCommands.VertSpaceConcatenate,
					MenuCommands.VertSpaceMakeEqual
				};

		}


		#region Add/Remove Command Handlers
		private void AddCommandHandlers()
		{
			if( _mcsHelper == null) return;

			_mcsHelper[MenuCommands.KeyMoveLeft].Change += new EventHandler(OnKeyMoveLeft);
			_mcsHelper[MenuCommands.KeyMoveRight].Change += new EventHandler(OnKeyMoveRight);
			_mcsHelper[MenuCommands.KeyMoveDown].Change += new EventHandler(OnKeyMoveDown);
			_mcsHelper[MenuCommands.KeyMoveUp].Change += new EventHandler(OnKeyMoveUp);

			_mcsHelper[MenuCommands.KeyNudgeDown].Change += new EventHandler(OnKeyNudgeDown);
			_mcsHelper[MenuCommands.KeyNudgeLeft].Change += new EventHandler(OnKeyNudgeLeft);
			_mcsHelper[MenuCommands.KeyNudgeRight].Change += new EventHandler(OnKeyNudgeRight);
			_mcsHelper[MenuCommands.KeyNudgeUp].Change += new EventHandler(OnKeyNudgeUp);

			_mcsHelper[MenuCommands.KeyNudgeHeightDecrease].Change += new EventHandler(OnKeyNudgeHeightDecrease);
			_mcsHelper[MenuCommands.KeyNudgeHeightIncrease].Change += new EventHandler(OnKeyNudgeHeightIncrease);
			_mcsHelper[MenuCommands.KeyNudgeWidthDecrease].Change += new EventHandler(OnKeyNudgeWidthDecrease);
			_mcsHelper[MenuCommands.KeyNudgeWidthIncrease].Change += new EventHandler(OnKeyNudgeWidthIncrease);

			_mcsHelper[MenuCommands.KeySizeWidthDecrease].Change += new EventHandler(OnKeySizeWidthDecrease);
			_mcsHelper[MenuCommands.KeySizeWidthIncrease].Change += new EventHandler(OnKeySizeWidthIncrease);
			_mcsHelper[MenuCommands.KeySizeHeightIncrease].Change += new EventHandler(OnKeySizeHeightIncrease);
			_mcsHelper[MenuCommands.KeySizeHeightDecrease].Change += new EventHandler(OnKeySizeHeightDecrease);
		
			_mcsHelper[MenuCommands.AlignLeft].Change += new EventHandler(OnAlignLeft);
			_mcsHelper[MenuCommands.AlignBottom].Change += new EventHandler(OnAlignBottom);
			_mcsHelper[MenuCommands.AlignRight].Change += new EventHandler(OnAlignRight);
			_mcsHelper[MenuCommands.AlignToGrid].Change +=  new EventHandler( OnAlignToGrid );
			_mcsHelper[MenuCommands.AlignTop].Change += new EventHandler(OnAlignTop);

			_mcsHelper[MenuCommands.AlignVerticalCenters].Change += new EventHandler(OnCenterVertically);
			_mcsHelper[MenuCommands.AlignHorizontalCenters].Change += new EventHandler(OnCenterHorizontally);
			_mcsHelper[MenuCommands.CenterVertically].Change += new EventHandler(OnCenterVertically);
			_mcsHelper[MenuCommands.CenterHorizontally].Change += new EventHandler(OnCenterHorizontally);
			
			_mcsHelper[MenuCommands.HorizSpaceDecrease].Change += new EventHandler(OnHorizSpaceDecrease);
			_mcsHelper[MenuCommands.HorizSpaceIncrease].Change += new EventHandler(OnHorizSpaceIncrease);
			_mcsHelper[MenuCommands.HorizSpaceMakeEqual].Change += new EventHandler(OnHorizSpaceMakeEqual);
			_mcsHelper[MenuCommands.HorizSpaceConcatenate].Change += new EventHandler(OnSizeToControlWidth);

			_mcsHelper[MenuCommands.SizeToControlHeight].Change += new EventHandler(OnSizeToControlHeight);
			_mcsHelper[MenuCommands.SizeToControl].Change += new EventHandler(OnSizeToControl);
			_mcsHelper[MenuCommands.SizeToControlWidth].Change += new EventHandler(OnSizeToControlWidth);
			_mcsHelper[MenuCommands.SizeToGrid].Change += new EventHandler(OnSizeToGrid);

			_mcsHelper[MenuCommands.VertSpaceDecrease].Change += new EventHandler(OnVertSpaceDecrease);
			_mcsHelper[MenuCommands.VertSpaceIncrease].Change += new EventHandler(OnVertSpaceIncrease);
			_mcsHelper[MenuCommands.VertSpaceMakeEqual].Change += new EventHandler(OnVertSpaceMakeEqual);
			_mcsHelper[MenuCommands.VertSpaceConcatenate].Change += new EventHandler(OnSizeToControlHeight);


		}

		private void RemoveCommandHandlers()
		{
			if( _mcsHelper == null) return;

			_mcsHelper[MenuCommands.KeyMoveLeft].Change -= new EventHandler(OnKeyMoveLeft);
			_mcsHelper[MenuCommands.KeyMoveRight].Change -= new EventHandler(OnKeyMoveRight);
			_mcsHelper[MenuCommands.KeyMoveDown].Change -= new EventHandler(OnKeyMoveDown);
			_mcsHelper[MenuCommands.KeyMoveUp].Change -= new EventHandler(OnKeyMoveUp);

			_mcsHelper[MenuCommands.KeyNudgeDown].Change -= new EventHandler(OnKeyNudgeDown);
			_mcsHelper[MenuCommands.KeyNudgeLeft].Change -= new EventHandler(OnKeyNudgeLeft);
			_mcsHelper[MenuCommands.KeyNudgeRight].Change -= new EventHandler(OnKeyNudgeRight);
			_mcsHelper[MenuCommands.KeyNudgeUp].Change -= new EventHandler(OnKeyNudgeUp);

			_mcsHelper[MenuCommands.KeyNudgeHeightDecrease].Change -= new EventHandler(OnKeyNudgeHeightDecrease);
			_mcsHelper[MenuCommands.KeyNudgeHeightIncrease].Change -= new EventHandler(OnKeyNudgeHeightIncrease);
			_mcsHelper[MenuCommands.KeyNudgeWidthDecrease].Change -= new EventHandler(OnKeyNudgeWidthDecrease);
			_mcsHelper[MenuCommands.KeyNudgeWidthIncrease].Change -= new EventHandler(OnKeyNudgeWidthIncrease);

			_mcsHelper[MenuCommands.KeySizeWidthDecrease].Change -= new EventHandler(OnKeySizeWidthDecrease);
			_mcsHelper[MenuCommands.KeySizeWidthIncrease].Change -= new EventHandler(OnKeySizeWidthIncrease);
			_mcsHelper[MenuCommands.KeySizeHeightIncrease].Change -= new EventHandler(OnKeySizeHeightIncrease);
			_mcsHelper[MenuCommands.KeySizeHeightDecrease].Change -= new EventHandler(OnKeySizeHeightDecrease);
		
			_mcsHelper[MenuCommands.AlignLeft].Change -= new EventHandler(OnAlignLeft);
			_mcsHelper[MenuCommands.AlignBottom].Change -= new EventHandler(OnAlignBottom);
			_mcsHelper[MenuCommands.AlignRight].Change -= new EventHandler(OnAlignRight);
			_mcsHelper[MenuCommands.AlignToGrid].Change -=  new EventHandler( OnAlignToGrid );
			_mcsHelper[MenuCommands.AlignTop].Change -= new EventHandler(OnAlignTop);

			_mcsHelper[MenuCommands.AlignVerticalCenters].Change -= new EventHandler(OnCenterVertically);
			_mcsHelper[MenuCommands.AlignHorizontalCenters].Change -= new EventHandler(OnCenterHorizontally);
			_mcsHelper[MenuCommands.CenterVertically].Change -= new EventHandler(OnCenterVertically);
			_mcsHelper[MenuCommands.CenterHorizontally].Change -= new EventHandler(OnCenterHorizontally);
			
			_mcsHelper[MenuCommands.HorizSpaceDecrease].Change -= new EventHandler(OnHorizSpaceDecrease);
			_mcsHelper[MenuCommands.HorizSpaceIncrease].Change -= new EventHandler(OnHorizSpaceIncrease);
			_mcsHelper[MenuCommands.HorizSpaceMakeEqual].Change -= new EventHandler(OnHorizSpaceMakeEqual);
			_mcsHelper[MenuCommands.HorizSpaceConcatenate].Change -= new EventHandler(OnSizeToControlWidth);

			_mcsHelper[MenuCommands.SizeToControlHeight].Change -= new EventHandler(OnSizeToControlHeight);
			_mcsHelper[MenuCommands.SizeToControl].Change -= new EventHandler(OnSizeToControl);
			_mcsHelper[MenuCommands.SizeToControlWidth].Change -= new EventHandler(OnSizeToControlWidth);
			_mcsHelper[MenuCommands.SizeToGrid].Change -= new EventHandler(OnSizeToGrid);

			_mcsHelper[MenuCommands.VertSpaceDecrease].Change -= new EventHandler(OnVertSpaceDecrease);
			_mcsHelper[MenuCommands.VertSpaceIncrease].Change -= new EventHandler(OnVertSpaceIncrease);
			_mcsHelper[MenuCommands.VertSpaceMakeEqual].Change -= new EventHandler(OnVertSpaceMakeEqual);
			_mcsHelper[MenuCommands.VertSpaceConcatenate].Change -= new EventHandler(OnSizeToControlHeight);

		}

		#endregion Add/Remove Command Handlers

		#region Command Handlers
		PropertyDescriptor	_shapePropPos	 = TypeDescriptor.GetProperties(typeof( Shape ))["Position"];
		PropertyDescriptor	_shapePropSize	 = TypeDescriptor.GetProperties(typeof( Shape ))["Size"];


		#region Key Move Shape
		private void KeyMoveShape( Point offset , bool snapToGrid, string txText)
		{
			if( !this.IsPrimarySelection) return;

			using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction(txText))
			{
				Shape shape = this.Shape;

				Point pos = shape.Position;
				pos.X += offset.X;
				pos.Y += offset.Y;

				if( snapToGrid ) 
				{
					pos = this.SnapGridPoint( pos );
					if( offset.X == 0) pos.X = shape.Position.X;
					if( offset.Y == 0) pos.Y = shape.Position.Y;
				}

				if( pos != shape.Position ) 
				{
					_shapePropPos.SetValue(shape,pos);
					tx.Commit();
				}
				else tx.Cancel();
			}


		}

		private void OnKeyMoveLeft(object sender, EventArgs e)
		{
			//int offset = _snapToGrid ? _gridSize.Width : 1;
			KeyMoveShape( new Point(-1,0 ), _snapToGrid, "Key:Move left");

		}

		private void OnKeyMoveRight(object sender, EventArgs e)
		{
			int offset = _snapToGrid ? _gridSize.Width : 1;
			KeyMoveShape(new Point(offset,0), _snapToGrid, "Key:Move right");


		}

		private void OnKeyMoveDown(object sender, EventArgs e)
		{
			int offset = _snapToGrid ? _gridSize.Height : 1;
			KeyMoveShape(new Point(0,offset), _snapToGrid,"Key:Move down");


		}

		private void OnKeyMoveUp(object sender, EventArgs e)
		{
			//int offset = _snapToGrid ? _gridSize.Height : 1;
			KeyMoveShape(new Point(0,-1), _snapToGrid, "Key:Move up");

		}

		
		private void OnKeyNudgeDown(object sender, EventArgs e)
		{
			int offset = !_snapToGrid ? _gridSize.Height : 1;
			KeyMoveShape(new Point(0,offset), !_snapToGrid, "Key:Nudge down");

		}

		private void OnKeyNudgeLeft(object sender, EventArgs e)
		{
			int offset = !_snapToGrid ? _gridSize.Width : 1;
			KeyMoveShape( new Point(-offset,0 ), !_snapToGrid, "Key:Nudge left");

		}

		private void OnKeyNudgeRight(object sender, EventArgs e)
		{
			int offset = !_snapToGrid ? _gridSize.Width : 1;
			KeyMoveShape(new Point(offset,0), !_snapToGrid, "Key:Nudge right");

		}

		private void OnKeyNudgeUp(object sender, EventArgs e)
		{
			int offset = !_snapToGrid ? _gridSize.Height : 1;
			KeyMoveShape(new Point(0,-offset), !_snapToGrid, "Key:Nudge up");

		}


		#endregion Key Move Shape
		
		#region Key resize Shape

		private void KeyResizeShape( Size offset , bool snapToGrid , string txText)
		{
			if( !this.IsPrimarySelection) return;

			using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction(txText))
			{
				Shape shape = this.Shape;

				Size size = shape.Size;
				size.Width	+= offset.Width;
				size.Height += offset.Height;

				if( snapToGrid )
				{
					Point pos = shape.Position;
					Point dSize = new Point( size );
					dSize.Offset( pos.X, pos.Y );
					dSize = this.SnapGridPoint( dSize );
					dSize.Offset( -pos.X, -pos.Y );
					
					size = new Size( dSize );

					if( offset.Width == 0)	size.Width	= shape.Size.Width;
					if( offset.Height == 0) size.Height = shape.Size.Height;
				}
				
				if( size != shape.Size ) {_shapePropSize.SetValue(shape,size);tx.Commit();}
				else tx.Cancel();
				
			}
		}


		private void OnKeySizeWidthDecrease(object sender, EventArgs e)
		{
			//int offset = _snapToGrid ? _gridSize.Width : 1;
			KeyResizeShape( new Size(-1,0 ), _snapToGrid, "Key:Decrease width");

		}

		private void OnKeySizeWidthIncrease(object sender, EventArgs e)
		{
			int offset = _snapToGrid ? _gridSize.Width : 1;
			KeyResizeShape(new Size(offset,0), _snapToGrid, "Key:Increase width");
		}

		private void OnKeySizeHeightDecrease(object sender, EventArgs e)
		{
			//int offset = _snapToGrid ? _gridSize.Width : 1;
			KeyResizeShape(new Size(0,-1), _snapToGrid, "Key:Decrease height");

		}

		private void OnKeySizeHeightIncrease(object sender, EventArgs e)
		{
			int offset = _snapToGrid ? _gridSize.Height : 1;
			KeyResizeShape(new Size(0,offset), _snapToGrid, "Key:Increase height");
		}


		private void OnKeyNudgeWidthDecrease(object sender, EventArgs e)
		{
			int offset = !_snapToGrid ? _gridSize.Width : 1;
			KeyResizeShape( new Size(-offset,0 ), !_snapToGrid, "Nudge:Decrease width");
		}

		private void OnKeyNudgeWidthIncrease(object sender, EventArgs e)
		{
			int offset = !_snapToGrid ? _gridSize.Width : 1;
			KeyResizeShape(new Size(offset,0), !_snapToGrid, "Nudge:Increase height");
		}

		private void OnKeyNudgeHeightDecrease(object sender, EventArgs e)
		{
			int offset = !_snapToGrid ? _gridSize.Width : 1;
			KeyResizeShape(new Size(0,-offset), !_snapToGrid, "Nudge:Decrease height");
		}

		private void OnKeyNudgeHeightIncrease(object sender, EventArgs e)
		{
			int offset = !_snapToGrid ? _gridSize.Height : 1;
			KeyResizeShape(new Size(0,offset), !_snapToGrid,"Nudge:Increase height");
		}


		#endregion Key resize Shape


		private void OnAlignToGrid(object sender, EventArgs e)
		{
			if( !this.IsPrimarySelection) return;

			using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction("Align to Grid"))
			{
				Point pos = this.SnapGridPoint(this.Shape.Position , true);
				if( pos != this.Shape.Position) {_shapePropPos.SetValue(this.Shape,pos); tx.Commit();}
				else tx.Cancel();
			}
				
		}


		private void OnAlignLeft(object sender, EventArgs e)
		{
			if( !this.IsPrimarySelection) return;
			using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction("Align left"))
			{
				Point pos = this.Shape.Position;
				if( pos.X != 0) pos.X = 0;
				if( pos != this.Shape.Position) {_shapePropPos.SetValue(this.Shape,pos); tx.Commit();}
				else tx.Cancel();
			}
		}



		private void OnAlignTop(object sender, EventArgs e)
		{
			if( !this.IsPrimarySelection) return;
			using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction("Align top"))
			{
				Point pos = this.Shape.Position;
				if( pos.Y != 0) pos.Y = 0;
				if( pos != this.Shape.Position) {_shapePropPos.SetValue(this.Shape,pos); tx.Commit();}
				else tx.Cancel();
			}

		}

		private void OnAlignRight(object sender, EventArgs e)
		{
			if( !this.IsPrimarySelection) return;
			using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction("Align right"))
			{
				Point pos = this.Shape.Position;
				pos.X = this.ShapeProvider.Size.Width - this.Shape.Size.Width;
				if( pos != this.Shape.Position) {_shapePropPos.SetValue(this.Shape,pos); tx.Commit();}
				else tx.Cancel();
			}
		}

		private void OnAlignBottom(object sender, EventArgs e)
		{
			if( !this.IsPrimarySelection) return;
			using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction("Align bottom"))
			{
				Point pos = this.Shape.Position;
				pos.Y = this.ShapeProvider.Size.Height - this.Shape.Size.Height;
				if( pos != this.Shape.Position) {_shapePropPos.SetValue(this.Shape,pos); tx.Commit();}
				else tx.Cancel();
			}
		}


		private void AlignToContainerCenter( bool horizontal , string txText)
		{
			if( !this.IsPrimarySelection) return;

			Point primCenter = Point.Round( RectangleUtil.CenterPoint( new Rectangle( Point.Empty, this.ShapeProvider.Size) ));
			using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction(txText))
			{
				Shape shape = this.Shape;
				Point pos  = shape.Position;
				Point center = Point.Round( RectangleUtil.CenterPoint ( shape.Bounds ) );
				if( horizontal ) 
				{
					int dx = center.X - primCenter.X;
					pos.X -= dx;
				}
				else  
				{
					int dy = center.Y - primCenter.Y;
					pos.Y -= dy;
				}

				if( pos != shape.Position ) { _shapePropPos.SetValue(shape,pos); tx.Commit();}
				else tx.Cancel();
			}

		}


		private void OnCenterHorizontally(object sender, EventArgs e)
		{
			AlignToContainerCenter( true,"Center horizontally");
		}

		private void OnCenterVertically(object sender, EventArgs e)
		{
			AlignToContainerCenter( false,"Center vertically");
		}

		private void OnHorizSpaceMakeEqual(object sender, EventArgs e)
		{
			if( !this.IsPrimarySelection) return;

			Rectangle controlBounds	= new Rectangle( Point.Empty, this.ShapeProvider.Size );
			Rectangle shapeBounds	= new Rectangle( this.Shape.Position, this.Shape.Size );
			if( Rectangle.Intersect( controlBounds, shapeBounds) == Rectangle.Empty)
			{
				this.OnSizeToControlWidth( sender, e );
				return;
			}

			using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction("Make horizontal spacing equal"))
			{
				Size size = this.Shape.Size;
				size.Width = this.ShapeProvider.Size.Width - (2*this.Shape.Position.X);

				if( size != this.Shape.Size) {_shapePropSize.SetValue(this.Shape,size); tx.Commit();}
				else tx.Cancel();
			}
		}
		
		private void OnVertSpaceMakeEqual(object sender, EventArgs e)
		{
			if( !this.IsPrimarySelection) return;
			Rectangle controlBounds	= new Rectangle( Point.Empty, this.ShapeProvider.Size );
			Rectangle shapeBounds	= new Rectangle( this.Shape.Position, this.Shape.Size );
			if( Rectangle.Intersect( controlBounds, shapeBounds) == Rectangle.Empty)
			{
				this.OnSizeToControlHeight( sender, e );
				return;
			}

			using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction("Make vertical spacing equal"))
			{
				Size size = this.Shape.Size;
				size.Height = this.ShapeProvider.Size.Height - (2*this.Shape.Position.Y) ;

				if( size != this.Shape.Size) {_shapePropSize.SetValue(this.Shape,size); tx.Commit();}
				else tx.Cancel();
			}
		}

		#region Inflate Shape Bounds

		private void InflateShapeBounds( int offset, bool horizontal, string txText)
		{
			if( !this.IsPrimarySelection) return;

			using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction(txText))
			{
				Rectangle bounds = Rectangle.Round( this.Shape.Bounds );
				if( horizontal) bounds.Inflate(offset, 0);
				else bounds.Inflate( 0, offset );

				if( bounds != Rectangle.Round( this.Shape.Bounds )) 
				{
					try
					{
						this.Shape.SuspendLayout();
						_shapePropPos.SetValue(this.Shape,bounds.Location); 
						_shapePropSize.SetValue(this.Shape,bounds.Size); 
						tx.Commit();
					}
					finally
					{
						this.Shape.ResumeLayout();
					}
				}
				else tx.Cancel();
			}
		}


		private void OnHorizSpaceDecrease(object sender, EventArgs e)
		{
			int offset = _snapToGrid ? _gridSize.Height : 1;
			InflateShapeBounds( -offset, true, "Decrease horizontal spacing");
		}

		private void OnHorizSpaceIncrease(object sender, EventArgs e)
		{
			int offset = _snapToGrid ? _gridSize.Height : 1;
			InflateShapeBounds( offset, true, "Increase horizontal spacing");
		}

		private void OnVertSpaceDecrease(object sender, EventArgs e)
		{
			int offset = _snapToGrid ? _gridSize.Height : 1;
			InflateShapeBounds( -offset, false, "Decrease vertical spacing");

		}

		private void OnVertSpaceIncrease(object sender, EventArgs e)
		{
			int offset = _snapToGrid ? _gridSize.Height : 1;
			InflateShapeBounds( offset, false, "Increase vertical spacing");
		}


		#endregion Inflate Shape Bounds
		
	
		private void OnSizeToControlHeight(object sender, EventArgs e)
		{
			if( !this.IsPrimarySelection) return;

			Size controlSize	= this.ShapeProvider.Size ;
			Rectangle shapeBounds	= new Rectangle( this.Shape.Position, this.Shape.Size );
			Rectangle origBounds	= shapeBounds;
			if( shapeBounds.Y==0 && shapeBounds.Height == controlSize.Height) return;
			shapeBounds.Y = 0;
			shapeBounds.Height = controlSize.Height;

			using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction("Make same width"))
			{
				this.Shape.SuspendLayout();

				_shapePropSize.SetValue(this.Shape,shapeBounds.Size); 
				_shapePropPos.SetValue(this.Shape,shapeBounds.Location); 
				
				if( shapeBounds != origBounds) tx.Commit();
				else tx.Cancel();

				this.Shape.ResumeLayout();
			}

		}

		private void OnSizeToControlWidth(object sender, EventArgs e)
		{
			if( !this.IsPrimarySelection) return;

			Size controlSize	= this.ShapeProvider.Size ;
			Rectangle shapeBounds	= new Rectangle( this.Shape.Position, this.Shape.Size );
			Rectangle origBounds	= shapeBounds;
			if( shapeBounds.X==0 && shapeBounds.Width == controlSize.Width ) return;
			shapeBounds.X = 0;
			shapeBounds.Width = controlSize.Width;

			using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction("Make same height"))
			{
				this.Shape.SuspendLayout();

				_shapePropSize.SetValue(this.Shape,shapeBounds.Size); 
				_shapePropPos.SetValue(this.Shape,shapeBounds.Location); 
				
				if( shapeBounds != origBounds) tx.Commit();
				else tx.Cancel();

				this.Shape.ResumeLayout();
			}
		}

		private void OnSizeToControl(object sender, EventArgs e)
		{
			if( !this.IsPrimarySelection) return;

			Rectangle controlBounds	= new Rectangle( Point.Empty, this.ShapeProvider.Size );
			Rectangle shapeBounds	= new Rectangle( this.Shape.Position, this.Shape.Size );
			Rectangle origBounds	= shapeBounds;
			if( shapeBounds == controlBounds) return;
			shapeBounds = controlBounds;

			using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction("Make same size"))
			{
				this.Shape.SuspendLayout();

				_shapePropSize.SetValue(this.Shape,shapeBounds.Size); 
				_shapePropPos.SetValue(this.Shape,shapeBounds.Location); 
				
				if( shapeBounds != origBounds) tx.Commit();
				else tx.Cancel();

				this.Shape.ResumeLayout();
			}

		}


		private void OnSizeToGrid(object sender, EventArgs e)
		{
			if( !this.IsPrimarySelection) return;

			using ( DesignerTransaction tx = this.DesignerHost.CreateTransaction("Make same size"))
			{
				this.Shape.SuspendLayout();

				Rectangle origBounds	= new Rectangle( this.Shape.Position, this.Shape.Size );

				Point pos = SnapGridPoint( origBounds.Location, true );
				if( pos != origBounds.Location) _shapePropPos.SetValue(this.Shape,pos);
 
				Size size =  new Size(this.SnapGridPoint( new Point( origBounds.Size ), true ));
				if( size != origBounds.Size) _shapePropSize.SetValue(this.Shape,size); 
				
				if( origBounds != this.Shape.Bounds ) tx.Commit();
				else tx.Cancel();

				this.Shape.ResumeLayout();
			}

		}

		

		#endregion Command Handlers

		#endregion MenuCommands and Event Handlers

	}
}
